﻿using System;
using System.Collections.Generic;
/*
COPYRIGHT (C) 2011-2013 Raynald Messié

THIS FILE IS PART OF SCRUMPILOT.

SCRUMPILOT IS FREE SOFTWARE: YOU CAN REDISTRIBUTE IT AND/OR MODIFY IT UNDER THE TERMS OF 
THE GNU LESSER GENERAL PUBLIC LICENSE VERSION v2.1 AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION.

SCRUMPILOT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY; WITHOUT
EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU LESSER
GENERAL PUBLIC LICENSE FOR MORE DETAILS.

YOU SHOULD HAVE RECEIVED A COPY OF THE GNU LESSER GENERAL PUBLIC LICENSE ALONG WITH SCRUMPILOT. 
IF NOT, SEE <HTTP://WWW.GNU.ORG/LICENSES/>.
*/

using System.Globalization;
using System.Linq;
using System.Web;
using ScrumPilot.Domain.Models;
using ScrumPilot.TFSHelpers;
using WorkItem = Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem;

namespace ScrumPilot.Domain
{
    public abstract class BusinessProcessLayer
    {
        protected const int Range = 7; // should be a parameters

        protected  String TFSRootUrl;
     
        protected static TFSServices TFS { get; set; }
        protected BusinessProcessLayer() { }

        protected BusinessProcessLayer(TFSServices tfs)
            : this()
        {
            TFS = tfs;
        }

        protected BusinessProcessLayer(TFSServices tfs, String tfsRootUrl)
            : this(tfs)
        {
            this.TFSRootUrl = tfsRootUrl;
        }

        protected List<WorkItem> WorkItemsList;

        private Int32[] _followedProject;

        protected Int32[] FollowedProject
        {
            get
            {
                using (var unitOfWork = new UnitOfWork())
                {
                    if (_followedProject == null || _followedProject.Count() == 0)
                        _followedProject = unitOfWork.ProjectRepository.GetFollowedProjectId();
                    return _followedProject;
                }
            }
        }

        private List<String> _followedProjectName;

        protected List<String> FollowedProjectName
        {
            get
            {
                using (var unitOfWork = new UnitOfWork())
                {
                    if (_followedProjectName == null || _followedProjectName.Count == 0)
                    {
                        var prjs = unitOfWork.ProjectRepository.GetFollowedProject();
                        this._followedProjectName = new List<string>(prjs.Count());
                        foreach (var project in prjs)
                        {
                            _followedProjectName.Add(project.name);
                        }
                    }
                    return _followedProjectName;
                }
            }
        }

        private Dictionary<string, string> _followedProjectsDictonary;

        protected IDictionary<string, string> FollowedProjectsDictonary
        {
            get
            {
                using (var unitOfWork = new UnitOfWork())
                {
                    if (_followedProjectsDictonary == null || !_followedProjectsDictonary.Any())
                    {
                        var prjs = unitOfWork.ProjectRepository.GetFollowedProject();
                        this._followedProjectsDictonary = new Dictionary<string, string>(prjs.Count());
                        foreach (var project in prjs)
                        {
                            _followedProjectsDictonary.Add(project.name, project.currentsprint);
                        }
                    }
                    return _followedProjectsDictonary;
                }
            }
        }

        protected IDictionary<int, string> FollowedProjectsIterationDictonary
        {
            get
            {
                using (var unitOfWork = new UnitOfWork())
                {
                    return unitOfWork.ProjectRepository.GetFollowedProjectDictionary();
                }
            }
        }

        private Dictionary<string, string> _currentSprintsDictonary;
        protected IDictionary<string, string> CurrentSprintsDictonary
        {
            get
            {
                using (var unitOfWork = new UnitOfWork())
                {
                    return this._currentSprintsDictonary ??
                           (this._currentSprintsDictonary = unitOfWork.SprintProjectIterationRepository.Filter(
                               p => p.sprint.state == (byte)SprintState.Current).Distinct()
                                                                      .ToDictionary(spn => spn.project.name,
                                                                                    spn => spn.currentsprint));
                }

            }
        }

        protected IDictionary<int, string> CurrentSprintsProjectIDDictonary()
        {
            using (var unitOfWork = new UnitOfWork())
            {
                return unitOfWork.SprintProjectIterationRepository.Filter(
                           p => p.sprint.state == (byte)SprintState.Current).Distinct()
                                                                  .ToDictionary(spn => spn.projectid,
                                                                                spn => spn.currentsprint);
            }
        }

        public tfsserverparam TFSParams
        {
            get
            {
                using (var unitOfWork = new UnitOfWork())
                {
                    return unitOfWork.TfsServerParamsRepository.GetOne();
                }
            }
        }

        public Int32 CurrentUserID { get; set; }

        private user _currentUser;

        public user CurrentUser
        {
            get
            {
                if (_currentUser == null)
                {
                    using (var unitOfWork = new UnitOfWork())
                    {
                        this._currentUser = unitOfWork.UserRepositery.GetFullById(this.CurrentUserID);
                    }
                }
                return this._currentUser;
            }
        }

        private List<Int32> _followedUsers;
        protected List<Int32> FollowedUsers
        {
            get
            {
                if (_followedUsers == null && CurrentUser != null)
                {
                    _followedUsers = CurrentUser.follow.Select(p => p.followeduserid).ToList();
                    _followedUsers.Add(CurrentUserID);
                }
                return _followedUsers;
            }
        }

        protected static CultureInfo CurrentCulture { get; set; }

        private SprintDefinition _currentSprint;

        public SprintDefinition CurrentSprint
        {
            get
            {
                if (_currentSprint == null)
                {
                    using (var unitOfWork = new UnitOfWork())
                    {
                        var spt = unitOfWork.SprintRepository.Get(p => p.state == (int)SprintState.Current && p.startdate != null && p.enddate != null);
                        if (spt != null && spt.startdate.HasValue && spt.enddate.HasValue)
                        {
                            _currentSprint = new SprintDefinition
                                                 {
                                                     ID = spt.sprintid,
                                                     Name = spt.name,
                                                     StartDate = spt.startdate.Value,
                                                     EndDate = spt.enddate.Value
                                                 };
                        }
                    }
                }
                return this._currentSprint;
            }
        }

        protected IList<WorkItemSimpleForUser> CopyAndMapFromTFS(IEnumerable<WorkItem> workItemlist)
        {
            var items = workItemlist as WorkItem[] ?? workItemlist.ToArray();
            var aRet = new List<WorkItemSimpleForUser>(items.Count());
            var templateUrl = this.TFSRootUrl + "{0}/_workItems#_a=edit&id={1}";

            aRet.AddRange(items.Select(workItem => new WorkItemSimpleForUser
            {
                ID = workItem.Id,
                Title = workItem.Title,
                Content = HttpUtility.HtmlEncode(workItem.Description),
                Url = String.Format(templateUrl, workItem.Project.Name, workItem.Id)
            }));

            return aRet;
        }
    }
}
